import 'package:sleep/db/export.dart';
import 'package:sleep/db/merroy_db.dart';
import 'package:sleep/single/analyze/base_analyze.dart';
import 'package:sleep/single/filter/base_filter.dart';
import 'package:sleep/single/find_peak.dart';
import 'package:sleep/single/point_model.dart';
import 'package:sleep/single/wave_show_model.dart';

const overWidth = 600;
const bufferWidth = 600;

class SleepAnalyze extends BaseAnayze {
  List<double> _orginData = [];
  final double mutilpe;
  List<SleepShowData> _waves = [];
  int _currentIndex = 0;
  SleepShowData? showModel;

  @override
  List<double> get points => _orginData;
  @override
  List<SleepShowData> get waves => _waves;
  @override
  int get currentIndex => _currentIndex;

  SleepAnalyze(this.mutilpe,
      {required List<BaseFliter> fliter, required List<BaseFliter> showFliter})
      : super(fliter, showFliter);

  bool turnOver = false;
  //定时给数据
  @override
  insertData(List<double> data) {
    final filterData = toFilter(data);
    timeIndex += 1;
    Export.share().save(filterData, CsvType.sleep);
    _orginData.addAll(filterData);
    hasTurnOff(data);
    realtimeData(_orginData.length >= 15000
        ? _orginData.sublist(_orginData.length - 15000)
        : _orginData);
    _currentIndex += filterData.length;
  }

  int timeIndex = 0;
  realtimeData(List<double> data) {
    //1s刷新一次
    if (timeIndex < 4) return;
    timeIndex = 0;
    List<SingeWaveModel> singWave = SleepWaveFind().findWave(data, 0);
    final List<SleepWave> fwave = findWave(singWave);
    final valu = MerroyDB.share().sleepValue == null
        ? null
        : (MerroyDB.share().sleepValue! / MerroyDB.share().sleepMutile!) *
            mutilpe;
    showModel = SleepShowData.fromWave(fwave, valu);

    if (showModel != null) {
      _waves.add(showModel!);
      Export.share()
          .save(null, CsvType.sleepwave, dataStr: [showModel!.toValue()]);
    }

    clearOverData();
  }

  clearOverData() {
    if (_orginData.length > 16000) {
      _orginData = _orginData.sublist(_orginData.length - 15000);
    }
    // if (_waves.length > 5000) {
    //   _waves = _waves.sublist(_waves.length - 4000);
    // }
  }

  hasTurnOff(List<double> data) {
    bool hasTurnoff = data.where((e) => e > 3510).isNotEmpty;
    turnOver = hasTurnoff;
  }

  List<SleepWave> findWave(List<SingeWaveModel> waves) {
    final List<SleepWave> fwave = [];
    if (waves.isEmpty) return fwave;
    SleepWave? beforeWhole;
    SingeWaveModel? inhale;
    SingeWaveModel? exhale;
    SingeWaveModel? beforeWave;
    for (final wave in waves) {
      if (beforeWave == null) {
        inhale = null;
        exhale = null;

        beforeWave = wave;
        continue;
      }

      if (wave.type == FatigueWaveType.positive) {
        //吸气
        inhale = wave;
      } else if (wave.type == FatigueWaveType.negative && inhale != null) {
        //呼气
        exhale ??= wave;
      }

      if (inhale != null && exhale != null) {
        SleepWave holeWave = SleepWave(exhale, inhale, beforeWhole);
        fwave.add(holeWave);
        beforeWhole = holeWave;
        inhale = null;
        exhale = null;
      }
    }

    return fwave;
  }

  @override
  clear() {
    _orginData.clear();
    _waves.clear();
    showModel = null;

    _currentIndex = 0;
  }
}

class SleepWaveFind {
  SleepWaveFind();

  List<SingeWaveModel> findWave(List<double> data, double startIndex) {
    List<SingeWaveModel> waves = [];

    //找到波峰波谷
    List<WavePoint> peaks = PeakFind.findPeaks(data,
        halfwindowSize: 20, startIndex: startIndex.toInt());

    //差值平均值
    final average = _WaveAverge(peaks);
    // List<WavePoint>
    // //求左右相邻的值 的 abs > 值 认为是动作
    // //查找peaks
    for (int i = 1; i < peaks.length - 1; i++) {
      final current = peaks[i];
      final pre = peaks[i - 1];
      final end = peaks[i + 1];
      final leftAmp = current.y - pre.y;
      final rightAmp = current.y - end.y;

      final type = (leftAmp > 0 && rightAmp > 0 && current.y.abs() > 0.08)
          ? FatigueWaveType.positive
          : (leftAmp < 0 && rightAmp < 0 && current.y.abs() > 0.08)
              ? FatigueWaveType.negative
              : null;

      if (type != null) {
        final isWave = isPeakWave(
            leftAmp,
            rightAmp,
            type == FatigueWaveType.positive
                ? average.positiveAverge
                : average.negativeAverge,
            current);
        if (isWave) {
          waves.add(
              SingeWaveModel(type: type, peak: current, start: pre, end: end));
        }
      }
    }

    return waves;
  }

  bool isPeakWave(double left, double right, double average, WavePoint peak) {
    const maxLRRate = 7;
    const minLRRate = 1 / maxLRRate;
    const averRate = 0.5;
    final lf = (left / right) < maxLRRate && (left / right) > minLRRate;
    final lfa = (left / average) > averRate || (right / average) > averRate;

    return lf && lfa;
  }
}

class _WaveAverge {
  final List<WavePoint> peaks;

  _WaveAverge(this.peaks) {
    findAverage(peaks);
  }

  final List<double> _positives = [];
  final List<double> _negatives = [];
  double get positiveAverge => _positives.isEmpty
      ? 0
      : _positives.reduce((a, b) => a + b) / _positives.length;

  double get negativeAverge => _negatives.isEmpty
      ? 0
      : _negatives.reduce((a, b) => a + b) / _negatives.length;
//睁闭眼的幅度计算的平均值
  findAverage(List<WavePoint> peaks) {
    for (int i = 1; i < peaks.length - 2; i++) {
      WavePoint prePeak = peaks[i - 1];
      WavePoint nextPeak = peaks[i + 1];
      WavePoint peak = peaks[i];
      double left = peak.y - prePeak.y;
      double right = peak.y - nextPeak.y;

      bool isA = _isAaverage(right / left);
      if (isA && left > 0) {
        _positives.add(left * 0.5 + right * 0.5);
      } else if (isA && left < 0) {
        _negatives.add(left * 0.5 + right * 0.5);
      }
    }
  }

  bool _isAaverage(double rate) {
    return rate <= 4 && rate >= 1 / 4;
  }
}
